#include "AsyncSocket.h"
#include "communication/DataPacket.h"

#include "../Session.h"
#define TIME_TIMEOUT (30*1000)
#define PACK_PACKET 0


AsyncSocket::AsyncSocket()
{
	SocketOps::InitSocket();
}

bool AsyncSocket::InitFD(HANDLE_FD fd, Session* pSession)
{
	if(fd == INVALID_FD)
	{
		m_fd = SocketOps::CreateTCPFileDescriptor();
	}
	else{
		m_fd = fd;
	}
	AsyncComm::InitFD( fd , pSession);
	return true;
}

AsyncSocket::~AsyncSocket()
{

}

bool AsyncSocket::Connect(const char * Address)
{
	std::string str_addr = Address;
	uint32 nPort = 7521;
	std::string::size_type pos2 = str_addr.rfind(":");
	if(pos2 != std::string::npos)
	{
		std::string str_port = str_addr.substr(pos2 + 1);
		const char* value = str_port.c_str();
		char* end;
		long n = strtol(value, &end, 0);
		nPort = end > value ? n : nPort;
	}

	std::string addr = str_addr.substr( 0 ,pos2 );

	struct hostent * ci = gethostbyname(addr.c_str());
	if(ci == 0)
		return false;

	m_address.sin_family = ci->h_addrtype;
	m_address.sin_port = ntohs((u_short)nPort);
	memcpy(&m_address.sin_addr.s_addr, ci->h_addr_list[0], ci->h_length);

	int32 iResult = connect(m_fd, (const sockaddr*)&m_address, sizeof(m_address)) ;
	
	if( iResult  == -1)
	{
		uint32 iError = GetLastError();
		if ( iError == ERROR_INPROGRESS || iError == ERROR_WOULDBLOCK )
		{
			return true;
		}else{
			this->_Reset();
			return false;
		}
	}else{
		OnConnect();
	}
	return true;
}


void AsyncSocket::Accept(sockaddr_in * address)
{
	memcpy(&m_address, address, sizeof(*address));
	_OnConnect();
}


uint32 AsyncSocket::GetLastError()
{
	return SocketOps::GetSocketError(m_fd);
}

int AsyncSocket::_RawReadData(char* pBuff, uint32 nBuffLen )
{
	int nRecv = recv(m_fd, pBuff, nBuffLen, 0) ;
	if( nRecv == SOCKET_ERROR)
	{
		uint32 err = GetLastError();
		if(err != ERROR_WOULDBLOCK)
		{
			OnDisconnect(err);
			return -1;
		}
	}
	return nRecv;
}

int AsyncSocket::_RawWriteDate(char* pBuff, uint32 nDataLen ) 
{
	int nSend = send(m_fd, pBuff, nDataLen , 0);
	if( nSend == SOCKET_ERROR)
	{
		uint32 err = GetLastError();
		if(err != ERROR_WOULDBLOCK)
		{
			OnDisconnect(err);
			return -1;
		}
	}
	return nSend;
}
	

bool AsyncSocket::CloseFD() 
{
	SocketOps::CloseSocket(m_fd);
	return true;
}

bool AsyncSocket::_NonblockingFD() 
{
	SocketOps::Nonblocking(m_fd);
	return true;

}